//游戏控制
import GameData, { moveCtrlStep, StepData } from "./GameData";
export default class GameDataCtrl {
    private static instance: GameDataCtrl = null;
    static getInstance() {
        if (!this.instance) {
            this.instance = new GameDataCtrl;
        }
        return this.instance;
    }
    private Data: GameData = GameData.getInstance();
    private historyCtrl: Array<Array<Array<number>>> = [];//历史操作数组
    private tweenArr: moveCtrlStep[];//变化数组
    //完善盘面信息
    init(center: cc.Node, borderSize: number) {
        let grdWidth = (center.width - borderSize * 3) / 4;
        this.Data.boardArr.forEach((arr, m) => {
            arr.forEach((step, n) => {
                step.x = grdWidth / 2 + grdWidth * n + borderSize * n;
                step.y = grdWidth / 2 + grdWidth * m + borderSize * m;
            })
        })
    }
    //重新开始游戏
    reset() {
        let lastData = this.Data.getData(GameData.DATA_KEY.GAME_BOARD);
        if (lastData && lastData instanceof Array) {//存在上次保存的数据
            this.setBoardStepData(lastData);
            this.Data.clearData(GameData.DATA_KEY.GAME_BOARD);
        } else {
            this.Data.boardList.forEach((step) => {
                step.num = 0;
                step.node = null;
            })
            if (this.Data.config.isFast && this.Data.historyScore > 4) {//快速游戏模式
                this.Data.historyScore = this.Data.historyScore > 1024 ? 1024 : this.Data.historyScore;
                this.randomItem(this.Data.historyScore);
            }
            this.randomItem(2,2);
        }
        this.checkGame();
        this.historyCtrl = [];
    }
    //随机生成num个指定数值value的item
    randomItem(value: number = 0, num: number = 1){
        let filterArr = this.Data.boardList.filter(step => step.num == 0);
        let arrLen = filterArr.length;
        let arr:StepData[] = [];
        if (arrLen > 0) {
            filterArr.sort((a, b) => Math.random() - 0.5);
            num = num > arrLen ? arrLen : num;
            for (let i = 0; i < num; i++) {
                if (value) {
                    filterArr[i].num = value;
                } else {
                    if (this.Data.config.isAnyStep && Math.random() > 0.98) {//任意牌
                        filterArr[i].num = 'X';
                    } else {
                        filterArr[i].num = 2;
                    }
                }
                arr.push(filterArr[i]);
            }
        }
        return arr;
    }
    //滑动 0左 1 右 2上 3下
    move(dir: number) {
        this.tweenArr = [];
        let lastBoard = this.getBoardStepConle();
        switch (dir) {
            case 0: {
                for (let m = 0; m < 4; m++) {
                    let lastN = 0;
                    for (let n = 1; n < 4; n++) {
                        let cur = this.Data.boardArr[m][n];
                        if (cur.num != 0) {
                            let last = this.Data.boardArr[m][lastN];
                            if (last.num == 0) {//空
                                this.moveStep(cur, last);
                            } else if (last.num == cur.num || last.num == 'X' || cur.num == 'X') {//吃
                                this.moveStep(cur, last);
                                lastN = lastN + 1;
                            } else {//让
                                lastN = lastN + 1;
                                if (lastN < n) {
                                    last = this.Data.boardArr[m][lastN];
                                    this.moveStep(cur, last);
                                }
                            }
                        }
                    }
                }
            }; break;
            case 1: {//右
                for (let m = 0; m < 4; m++) {
                    let lastN = 3;
                    for (let n = 2; n >= 0; n--) {
                        let cur = this.Data.boardArr[m][n];
                        if (cur.num != 0) {
                            let last = this.Data.boardArr[m][lastN];
                            if (last.num == 0) {//空
                                this.moveStep(cur, last);
                            } else if (last.num == cur.num || last.num == 'X' || cur.num == 'X') {//吃
                                this.moveStep(cur, last);
                                lastN = lastN - 1;
                            } else {//让
                                lastN = lastN - 1;
                                if (lastN > n) {
                                    last = this.Data.boardArr[m][lastN];
                                    this.moveStep(cur, last);
                                }
                            }
                        }
                    }
                }
            }; break;
            case 2: {//上
                for (let m = 0; m < 4; m++) {
                    let lastN = 3;
                    for (let n = 2; n >= 0; n--) {
                        let cur = this.Data.boardArr[n][m];
                        if (cur.num != 0) {
                            let last = this.Data.boardArr[lastN][m];
                            if (last.num == 0) {//空
                                this.moveStep(cur, last);
                            } else if (last.num == cur.num || last.num == 'X' || cur.num == 'X') {//吃
                                this.moveStep(cur, last);
                                lastN = lastN - 1;
                            } else {//让
                                lastN = lastN - 1;
                                if (lastN > n) {
                                    last = this.Data.boardArr[lastN][m];
                                    this.moveStep(cur, last);
                                }
                            }
                        }
                    }
                }
            }; break;
            case 3: {//下
                for (let m = 0; m < 4; m++) {
                    let lastN = 0;
                    for (let n = 1; n < 4; n++) {
                        let cur = this.Data.boardArr[n][m];
                        if (cur.num != 0) {
                            let last = this.Data.boardArr[lastN][m];
                            if (last.num == 0) {//空
                                this.moveStep(cur, last);
                            } else if (last.num == cur.num || last.num == 'X' || cur.num == 'X') {//吃
                                this.moveStep(cur, last);
                                lastN = lastN + 1;
                            } else {//让
                                lastN = lastN + 1;
                                if (lastN < n) {
                                    last = this.Data.boardArr[lastN][m];
                                    this.moveStep(cur, last);
                                }
                            }
                        }
                    }
                }
            }; break;
        }
        if (this.tweenArr.length > 0) {
            this.historyCtrl.push(lastBoard);
        }
        return this.tweenArr;
    }
    //移动位置
    moveStep(start: StepData, end: StepData) {
        if (end.num == 0 || end.num == start.num || end.num == 'X' || start.num == 'X') {
            let endNum: string | number;
            if (end.num == 'X' && start.num == 'X') {
                endNum = 'X';
            } else if (end.num == 'X') {
                endNum = Number(start.num) + Number(start.num);
            } else if (start.num == 'X') {
                if (end.num == 0) {
                    endNum = 'X';
                } else {
                    endNum = Number(end.num) + Number(end.num);
                }
            } else {
                endNum = Number(start.num) + Number(end.num);
            }
            if (end.num == 0) {//移动
                this.tweenArr.push({
                    node: start.node,
                    num: endNum,
                    Spos: cc.v3(start.x, start.y, 0),
                    Epos: cc.v3(end.x, end.y, 0),
                    Sopa: 255,
                    Eopa: 255,
                })
            } else {//吃
                this.tweenArr.push({
                    node: start.node,
                    num: endNum,
                    Spos: cc.v3(start.x, start.y, 0),
                    Epos: cc.v3(end.x, end.y, 0),
                    Sopa: 255,
                    Eopa: 255,
                })
                this.tweenArr.push({
                    node: end.node,
                    num: endNum,
                    Spos: cc.v3(end.x, end.y, 0),
                    Epos: cc.v3(end.x, end.y, 0),
                    Sopa: 255,
                    Eopa: 0,
                })
            }
            end.num = endNum;
            end.node = start.node;
            start.node = null;
            start.num = 0;
        }
    }
    //检查游戏状态
    checkGame() {
        let gameOver = true;
        for (let m = 0; m < 4; m++) {
            for (let n = 0; n < 4; n++) {
                let curNum: any = this.Data.boardArr[m][n].num;
                if (curNum != 'X') {
                    this.Data.curScore = this.Data.curScore < curNum ? curNum : this.Data.curScore;
                }
                let a = m > 0 ? this.Data.boardArr[m - 1][n] : null;
                let b = n > 0 ? this.Data.boardArr[m][n - 1] : null;
                let c = n < 3 ? this.Data.boardArr[m][n + 1] : null;
                let d = m < 3 ? this.Data.boardArr[m + 1][n] : null;
                if ((a && (a.num == 0 || a.num == curNum || a.num == 'X' || curNum == 'X')) ||
                    (b && (b.num == 0 || b.num == curNum || b.num == 'X' || curNum == 'X')) ||
                    (c && (c.num == 0 || c.num == curNum || c.num == 'X' || curNum == 'X')) ||
                    (d && (d.num == 0 || d.num == curNum || d.num == 'X' || curNum == 'X'))) {
                    gameOver = false;
                }
            }
        }
        if (gameOver) {
            this.Data.saveScore();
        }
        return gameOver;
    }
    //获取用户配置信息
    getUserConfig() {
        return this.Data.config;
    }
    //得到当前分数
    getCurScore() {
        return this.Data.curScore;
    }
    //获取历史分数
    getHistoryScore() {
        return this.Data.historyScore;
    }
    //获取颜色配置
    getItemColor(num: number | string) {
        let color = this.Data.itemColor[num];
        color = color ? color : this.Data.itemColor[2048];
        return color;
    }
    //获取历史操作数据
    getHistoryCtrlData() {
        return this.historyCtrl;
    }
    //获取移动数据
    getMoveData() {
        return this.tweenArr;
    }
    //获取当前的所有棋座
    getAllStep() {
        return this.Data.boardList;
    }
    //保存游戏进度
    saveGameData() {
        this.Data.saveData(GameData.DATA_KEY.GAME_BOARD, this.getBoardStepConle());
    }
    //保存游戏配值
    saveUserConfig() {
        this.Data.saveData(GameData.DATA_KEY.USER_CONFIG, this.Data.config);
    }
    //获取当前盘面数据-克隆
    getBoardStepConle() {
        let curBoardArr = [];
        this.Data.boardArr.forEach((arr, m) => {
            curBoardArr[m] = [];
            arr.forEach((step, n) => {
                curBoardArr[m][n] = step.num;
            })
        })
        return curBoardArr;
    }
    //设置当前盘面数据
    setBoardStepData(lastData: Array<Array<number>>) {
        this.Data.boardArr.forEach((arr, m) => {
            arr.forEach((step, n) => {
                step.num = lastData[m][n];
            })
        });
    }
    //上一步
    onPre() {
        if (this.historyCtrl.length > 0) {
            let last = this.historyCtrl.pop();
            this.setBoardStepData(last);
            this.checkGame();
        }
    }
}


